package com.yzc.rabbit;

import com.yzc.apis.logClient.MainOrderLogClient;
import com.yzc.constants.MqConstants;
import com.yzc.mapper.TicketMainOrderMapper;
import com.yzc.model.entity.ticket_order.OrderMain;
import com.yzc.model.entity.log.OrderStatusLog;
import com.yzc.redis.RedisUtil;
import com.yzc.util.RabbitMQUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import static com.yzc.constant.RedisConstant.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class OrderConsumerService {

    private final InventoryService inventoryService;
    private final TicketMainOrderMapper orderMainMapper;
    private final ConcurrentHashMap<Long, Integer> delayIndexMap = new ConcurrentHashMap<>();
    private final RabbitMQUtil rabbitMQUtil;
    private final RedisUtil redisUtil;
    private final MainOrderLogClient mainClient;

    /**
     * 处理未支付订单延迟消息
     *
     * @param orderId 订单ID
     */
    @RabbitListener(queues = MqConstants.ORDER_UNPAID_QUEUE)
    public void handleUnpaidOrder(Long orderId) {
        log.info(" [x] 收到未付款的订单消息，订单ID为: {}", orderId);

        try {
            // 1. 获取订单信息（优先从缓存中获取）
            OrderMain order = getOrderFromCacheOrDb(orderId);
            if (order == null) {
                log.error("RabbitMQ获取订单失败，订单不存在，订单ID: {}", orderId);
                return;
            }

            // 2. 检查订单是否已经支付成功
            if (OrderStatus.status_PAID.getCode() == order.getOrderStatus()) {
                log.info("订单已支付成功，无需回滚库存，订单ID: {}", orderId);
                return;
            }

            // 3. 检查订单状态是否为未支付
            if (OrderStatus.status_UNPAID.getCode() != order.getOrderStatus()) {
                log.info("订单状态已更新，无需回滚库存，订单ID: {}", orderId);
                return;
            }

            // 4. 幂等性检查：检查库存是否已经回滚
            if (inventoryService.isInventoryRolledBack(orderId)) {
                log.info("库存已回滚，无需重复操作，订单ID: {}", orderId);
                return;
            }

            // 5. 回滚库存
            inventoryService.rollbackInventory(orderId);
            log.info(" [x] 回滚订单ID的库存: {}", orderId);

            // 6. 更新主订单状态和失败原因
            updateOrderStatus(orderId, OrderStatus.status_CANCELED.getCode());
            log.info(" [x] 更新主订单状态为已取消，订单ID: {}", orderId);

            // 7. 记录操作日志
            logOrderStatusChange(orderId, OrderStatus.status_CANCELED.getCode());
            log.info(" [x] 记录操作日志，订单ID: {}", orderId);

            // 8. 发送延迟 30 分钟的消息
            rabbitMQUtil.sendStaggeredDelayedMessages(
                    MqConstants.DELAY_EXCHANGE_NAME,
                    "order.unpaid",
                    orderId
            );
            log.info(" [x] 发送延迟 30 分钟的消息，订单ID: {}", orderId);

        } catch (Exception e) {
            log.error("处理未支付订单失败，订单ID: {}", orderId, e);
            throw new RuntimeException("处理未支付订单失败", e);
        }
    }

    /**
     * 从缓存或数据库中获取订单信息
     */
    private OrderMain getOrderFromCacheOrDb(Long orderId) {
        String cacheKey = ORDER_RECORD_MAIN + orderId;
        OrderMain order = (OrderMain) redisUtil.get(cacheKey);
        if (order == null) {
            order = orderMainMapper.selectById(orderId);
            if (order != null) {
                // 将订单信息写入缓存
                redisUtil.set(cacheKey, order, CACHE_EXPIRE_TIME + new Random().nextInt(CACHE_RANDOM_RANGE));
            }
        }
        return order;
    }

    /**
     * 更新订单状态和失败原因
     */
    private void updateOrderStatus(Long orderId, int status) {
        OrderMain order = new OrderMain();
        order.setOrderId(orderId);
        order.setOrderStatus(status);
        order.setCancelReason("订单未支付，库存已回滚");
        orderMainMapper.updateById(order);

        // 更新缓存
        String cacheKey = ORDER_RECORD_MAIN + orderId;
        redisUtil.set(cacheKey, order, CACHE_EXPIRE_TIME + new Random().nextInt(CACHE_RANDOM_RANGE));
    }

    /**
     * 记录订单状态变更日志
     */
    private void logOrderStatusChange(Long orderId, int status) {
        OrderStatusLog orderStatusLog = new OrderStatusLog();
        orderStatusLog.setOrderId(orderId);
        orderStatusLog.setStatus(status);
        orderStatusLog.setRemark("订单未支付，库存已回滚");
        orderStatusLog.setOperator("system");
        orderStatusLog.setCreateTime(new Date());
        mainClient.createOrderLog(orderStatusLog);
    }
}